/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is mozilla.org code.
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Dou Yongwang <douyonwang@gmail.com> (Symbian port)
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "universalchardet.h"
//#include "nsUniversalDetector.h"
#include "nsUniversalChardetImpl.h"
#include <f32file.h>

#define MAXBSIZE (1L << 13)

const TUint KMinBlockSize = 256;
const TUint KMaxBlockSize = MAXBSIZE;
const TUint KDefaultBlockSize = 1024;

CUniversalChardet::CUniversalChardet() : iBlockSize(KDefaultBlockSize)
	{
	// No implementation required
	}

CUniversalChardet::~CUniversalChardet()
	{
	delete iDetector;
	delete iCharset;
	}

CUniversalChardet* CUniversalChardet::NewLC(CUniversalChardet::TFilter aFilter)
	{
	CUniversalChardet* self = new (ELeave) CUniversalChardet();
	CleanupStack::PushL(self);
	self->ConstructL(aFilter);
	return self;
	}

CUniversalChardet* CUniversalChardet::NewL(CUniversalChardet::TFilter aFilter)
	{
	CUniversalChardet* self = CUniversalChardet::NewLC(aFilter);
	CleanupStack::Pop(); // self;
	return self;
	}

void CUniversalChardet::ConstructL(CUniversalChardet::TFilter aFilter)
	{
	// just assign aFilter to filter, because the definitions of them are same.
	unsigned int filter  = aFilter;
	iDetector = new nsUniversalChardetImpl(filter);
	User::LeaveIfNull(iDetector);
	
	iCharset = KNullDesC8().AllocL();
	}

void CUniversalChardet::DetectL(const TDesC& aFilePath, TInt aBlockSize)
	{
	if (aBlockSize > 0)
		SetBlockSize(aBlockSize);
	
	RFs fs;
	User::LeaveIfError(fs.Connect());
	CleanupClosePushL(fs);
	RFile file;
	User::LeaveIfError(file.Open(fs, aFilePath, EFileRead));
	CleanupClosePushL(file);
	
	TInt sz;
	User::LeaveIfError(file.Size(sz));
	HBufC8* buf = HBufC8::NewLC(iBlockSize);
	TPtr8 ptr(buf->Des());
	nsresult rev = NS_OK;
	PRBool done = PR_FALSE;
	do
		{
		User::LeaveIfError(file.Read(ptr, Min(sz, iBlockSize)));
		if(!done)
			{
	        rev = iDetector->HandleData((const char*)buf->Ptr(), Min(sz, iBlockSize));
	        if(NS_FAILED(rev))
	        	{
//				SetCharsetL(KNullDesC8);
				break;
	        	}
			}
	    sz -= iBlockSize;
		} 
	while((sz > 0) && (!((nsUniversalChardetImpl*)iDetector)->done()));
	
	iDetector->DataEnd();
	
	TPtrC8 charset((const TText8*)((nsUniversalChardetImpl*)iDetector)->Charset());
	SetCharsetL(charset);
	
	CleanupStack::PopAndDestroy(3, &fs); // buf, file, fs
	}

void CUniversalChardet::SetBlockSize(TInt aBlockSize)
	{
	iBlockSize = aBlockSize;
	if (iBlockSize < KMinBlockSize)
		iBlockSize = KMinBlockSize;
	if (iBlockSize > KMaxBlockSize)
		iBlockSize = KMaxBlockSize;
	}

void CUniversalChardet::SetCharsetL(const TDesC8& aCharset)
	{
	HBufC8* charset = aCharset.AllocL();
	delete iCharset; iCharset = charset;
	}

const TPtrC8 CUniversalChardet::Charset() const
	{
	return *iCharset;
	}
